package com.passer.toolbox.common.network.util;

import com.passer.toolbox.common.core.util.CmdUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.SocketException;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class IPUtils {

    /**
     * 获取正在使用的网络适配器名称
     *
     * @return 网络适配器名称
     */
    public static String getNetInterfaceName() throws IOException {
        if (checkWifiConnection()) {
            return "WLAN";
        }
        String cmd = "netsh interface show interface";
        String name = "";
        String result = CmdUtils.runCmd(cmd);
        Pattern pattern = Pattern.compile("Enabled +Connected.*?(以太网 \\d)");
        Matcher matcher = pattern.matcher(result);
        if (matcher.find()) {
            name = matcher.group(1);
        } else {
            pattern = Pattern.compile("已启用 +已连接.*?(以太网 \\d)");
            matcher = pattern.matcher(result);
            if (matcher.find()) {
                name = matcher.group(1);
            }
        }
        return name;
    }

    /**
     * 检查 WIFI 是否连接
     *
     * @return boolean
     */
    public static boolean checkWifiConnection() throws IOException {
        String cmd = "netsh wlan show interface";
        String result = CmdUtils.runCmd(cmd);
        Pattern pattern = Pattern.compile("(已连接|connected)");
        Matcher matcher = pattern.matcher(result);
        return matcher.find();
    }

    /**
     * 检查指定网络适配器自动获取IP是否开启
     *
     * @param interfaceName 网络适配器名称
     * @return boolean
     * @throws IOException IO异常
     */
    public static boolean checkDHCP(String interfaceName) throws IOException {
        String cmd = "netsh interface ipv4 show addresses name = \"" + interfaceName + "\"";
        String result = CmdUtils.runCmd(cmd);
        Pattern pattern = Pattern.compile("Yes");
        Matcher matcher = pattern.matcher(result);
        return matcher.find();
    }

    /**
     * 检查自动获取IP是否开启
     *
     * @return boolean
     * @throws IOException IO异常
     */
    public static boolean checkDHCP() throws IOException {
        String interfaceName = getNetInterfaceName();
        return checkDHCP(interfaceName);
    }

    public static String getIPV4Method() throws IOException {
        boolean isDHCP = checkDHCP();
        if (isDHCP) {
            return "自动获取IPV4";
        }
        return "静态IPV4";
    }

    /**
     * 设置静态IPV4
     *
     * @param ip         IP
     * @param gateway    网关
     * @param isIntranet 是否是内网
     * @return boolean
     */
    public static boolean setStaticIPV4(String ip, String gateway, boolean isIntranet) throws IOException {
        /*
        source=dhcp  动态获取IP
        source=static  设置静态IP
         */

        // String interfaceName = getNetInterfaceName();
        String netInterfaceName = "以太网 2";
        String cmd = "netsh interface ipv4 set address name = \"" + netInterfaceName + "\" source = static address = " + ip + " gateway = " + gateway;
        if (!setIPV4(cmd)) return false;
        // 如果不是内网，检查网络是否连通
        if (!isIntranet) {
            int i = 0;
            // 等待ip更改完毕
            Optional<Inet4Address> ip4Address = Optional.empty();
            while (i++ < 10) {
                try {
                    Thread.sleep(500);
                    ip4Address = NetworkUtils.getLocalIp4Address();
                } catch (InterruptedException | SocketException e) {
                    log.error("【setStaticIPV4】循环【{}】获取IPV4地址失败：{}", i, e.getMessage());
                }
                if (ip4Address.isPresent() && ip.equals(ip4Address.get().getHostAddress())) {
                    break;
                }
            }
            // 检查网络是否连通
            return NetworkUtils.checkNetwork();
        }
        return true;
    }

    /**
     * 设置动态获取IPV4
     *
     * @param isIntranet 是否为内网
     * @return 是否设置成功
     */
    public static boolean setDynamicIPV4(boolean isIntranet) throws IOException {
        String interfaceName = getNetInterfaceName();
        boolean isDHCP = false;
        try {
            isDHCP = checkDHCP(interfaceName);
        } catch (IOException e) {
            log.error("【setDynamicIPV4】检查网络失败：{}", e.getMessage());
        }
        /*
        source=dhcp  动态获取IP
        source=static  设置静态IP
         */
        if (!isDHCP) {
            String cmd = "netsh interface ipv4 set address name = \"" + interfaceName + "\" source = dhcp";
            if (!setIPV4(cmd)) return false;
            // 等待ip更改完毕
            for (int i = 0; i < 20; i++) {
                try {
                    Thread.sleep(500);
                    isDHCP = checkDHCP(interfaceName);
                } catch (InterruptedException | IOException e) {
                    log.error("【setDynamicIPV4】循环【{}】检查网络失败：{}", i, e.getMessage());
                }
                if (isDHCP) break;
            }
            // 如果不是内网，检查网络是否连通
            if (!isIntranet) {
                // 检查网络是否连通
                return NetworkUtils.checkNetwork();
            }
        }
        return true;
    }

    /**
     * 修改IPV4
     *
     * @param cmd 修改命令
     * @return boolean
     */
    private static boolean setIPV4(String cmd) throws IOException {
        String result = CmdUtils.runCmd(cmd);
        // 如果运行命令后有打印值就没修改成功
        return Objects.equals(result, "");
    }


    /**
     * 设置随机静态IP
     *
     * @param gateway    网关
     * @param isIntranet 是否是内网
     * @return boolean 是否设置成功
     */
    public static boolean setRandomIP(String gateway, boolean isIntranet) throws IOException {
        String[] ips = gateway.split("\\.");
        String ip = ips[0] + "." + ips[1] + "." + ips[2] + ".";
        for (int i = 1; i < 255; i++) {
            if (ips[3].equals(i + "")) {
                continue;
            }
            if (setStaticIPV4(ip + i, gateway, isIntranet)) {
                return true;
            }
        }
        return false;
    }
}
